package assignmentImplementation;


import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;

import java.util.List;

import javax.jws.WebMethod;
import javax.jws.WebService;

import keyValueBaseExceptions.BeginGreaterThanEndException;
import keyValueBaseExceptions.KeyAlreadyPresentException;
import keyValueBaseExceptions.KeyNotFoundException;
import keyValueBaseExceptions.ServiceAlreadyInitializedException;
import keyValueBaseExceptions.ServiceInitializingException;
import keyValueBaseExceptions.ServiceNotInitializedException;
import keyValueBaseInterfaces.Pair;
import keyValueBaseInterfaces.Predicate;

@WebService
public class KeyValueBaseImpl 
{
	
	private IndexImpl index;
	private String storeFileName;
	
	
	public KeyValueBaseImpl(IndexImpl anIndex, String aStoreName) {

		this.index = anIndex;
		this.storeFileName = aStoreName;
		
	}

	@WebMethod
	public void init(String serverFilename)
			throws ServiceAlreadyInitializedException,
			ServiceInitializingException, FileNotFoundException {

		if(index.storeIsInit()){
			 throw new ServiceAlreadyInitializedException();
		}
		else{
			
			index.StoreInit(this.storeFileName);
			index.initFile(serverFilename);

		}
	}

	@WebMethod
	public ValueListImpl read(KeyImpl k) throws KeyNotFoundException,
			IOException, ServiceNotInitializedException {
			if(!index.storeIsInit()){
				throw new ServiceNotInitializedException();
			}
			else{
				return index.get(k);
			}
	}

	@WebMethod
	public void insert(KeyImpl k, ValueListImpl v)
			throws KeyAlreadyPresentException, IOException,
			ServiceNotInitializedException {

		if(!index.storeIsInit()){
			throw new ServiceNotInitializedException();
		}
		else{
			index.insert(k, v);
		}
	
	}

	@WebMethod
	public void update(KeyImpl k, ValueListImpl newV)
			throws KeyNotFoundException, IOException,
			ServiceNotInitializedException {


		if(!index.storeIsInit()){
		
			throw new ServiceNotInitializedException();
		}
		else{
			index.update(k, newV);
		}
		
	}

	@WebMethod
	public void delete(KeyImpl k) throws KeyNotFoundException,
			ServiceNotInitializedException {
	
		if(!index.storeIsInit()){
			throw new ServiceNotInitializedException();
		}
		else{
			index.remove(k);
		}
	
	}

	@WebMethod
	public List<ValueListImpl> scan(KeyImpl begin, KeyImpl end, Predicate<ValueListImpl> p)
			throws IOException, BeginGreaterThanEndException,
			ServiceNotInitializedException {

		if(!index.storeIsInit()){
			throw new ServiceNotInitializedException();
		}
		else{
			
			List<ValueListImpl> target = new ArrayList<ValueListImpl>();
			List<ValueListImpl> l = index.scan(begin, end);
			Iterator<ValueListImpl> iter = l.iterator();
			while(iter.hasNext()){
				ValueListImpl next = iter.next();
				if(p.evaluate(next)){
					target.add(next);
				}
			}
			return target;
		}
		
	}
	//Probably we need to use the unimplemented atomicscan function in index.
	@WebMethod
	public List<ValueListImpl> atomicScan(KeyImpl begin, KeyImpl end,
			Predicate<ValueListImpl> p) throws IOException,
			BeginGreaterThanEndException, ServiceNotInitializedException {

		if(!index.storeIsInit()){
			throw new ServiceNotInitializedException();
		}
		else{
			// this needs further checking
			return index.scan(begin, end);
		}

	}

	@WebMethod
	public void bulkPut(List<Pair<KeyImpl, ValueListImpl>> mappings)
			throws IOException, ServiceNotInitializedException {
		// Check if the key exists , if so just do an insert, otherwise do an update,
		// until the list is empty.

		if(!index.storeIsInit()){
			throw new ServiceNotInitializedException();
		}
		else{
			// this needs further checking
			this.index.bulkPut(mappings);
		}	

		
	}

}
